using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Utils.Extends;

namespace Utils.MonoInject
{
    /// <summary>
    /// Mono自动注入扩展方法 - 提供组件自动注入功能
    ///
    /// 主要功能：
    /// - 自动查找并注入标记了 [AutoInject] 和 [AutoInjectCollection] 的字段
    /// - 支持按名称精确查找和模糊查找
    /// - 支持集合类型的自动注入
    /// - 自动调用实现了 IMonoInitializer 接口的 Initialize() 方法
    ///
    /// 使用示例：
    /// public class PlayerController : MonoBehaviour, IMonoInitializer
    /// {
    ///     [AutoInject] private Rigidbody rb;
    ///     [AutoInjectCollection] private Collider[] allColliders;
    ///
    ///     public void Initialize()
    ///     {
    ///         // 初始化逻辑
    ///     }
    ///
    ///     private void Awake()
    ///     {
    ///         this.Initialize(); // 初始化
    ///     }
    /// }
    /// </summary>
    public static class MonoInjectExtensions
    {
        /// <summary>
        /// 初始化依赖的组件到标记了 [AutoInject] 和 [AutoInjectCollection] 的字段中
        /// 根据属性的配置自动查找对应的 Component 并赋值给字段
        /// </summary>
        /// <param name="behaviour">要初始化依赖组件的 MonoBehaviour 对象</param>
        public static void Initialize(this MonoBehaviour behaviour)
        {
            FieldInfo[] fields = behaviour.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

            foreach (FieldInfo field in fields)
            {
                // 检查字段是否标记了 AutoInjectCollectionAttribute（优先处理集合）
                AutoInjectCollectionAttribute searchComponents = field.GetCustomAttribute<AutoInjectCollectionAttribute>();
                if (searchComponents != null)
                {
                    InjectAutoInjectCollection(behaviour, field, searchComponents);
                    continue;
                }

                // 检查字段是否标记了 AutoInjectAttribute
                AutoInjectAttribute searchComponent = field.GetCustomAttribute<AutoInjectAttribute>();
                if (searchComponent == null)
                    continue;

                // 处理集合类型（数组、列表等）
                if (IsCollectionType(field.FieldType))
                {
                    InjectCollectionComponents(behaviour, field, searchComponent);
                }
                // 处理单个组件类型
                else if (typeof(Component).IsAssignableFrom(field.FieldType))
                {
                    InjectSingleComponent(behaviour, field, searchComponent);
                }
                else
                {
                    Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 的类型 '{field.FieldType.Name}' 不是 Component 类型或集合类型，已跳过...", behaviour);
                }
            }

            if (behaviour is IMonoInitializer initializer)
                initializer.OnInitialize();
        }

        /// <summary>
        /// 注入组件集合（使用 AutoInjectCollectionAttribute）
        /// </summary>
        private static void InjectAutoInjectCollection(MonoBehaviour behaviour, FieldInfo field, AutoInjectCollectionAttribute search)
        {
            // 验证字段类型必须是集合类型
            if (!IsCollectionType(field.FieldType))
            {
                Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 的类型 '{field.FieldType.Name}' 不是集合类型，已跳过...", behaviour);
                return;
            }

            Type elementType = GetCollectionElementType(field.FieldType);
            if (elementType == null || !typeof(Component).IsAssignableFrom(elementType))
            {
                Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 的集合元素类型 '{elementType?.Name}' 不是 Component 类型，已跳过...", behaviour);
                return;
            }

            // 使用 GetComponentsInChildren 查找所有匹配的组件
            Component[] components = behaviour.GetComponentsInChildren(elementType, search.IncludeInactive);

            // 将找到的组件集合转换为目标集合类型并赋值给字段
            object collection = ConvertToCollectionType(components, field.FieldType, elementType);
            field.SetValue(behaviour, collection);

            // 输出查找结果信息
            if (components.Length == 0)
            {
                Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 未找到任何匹配的组件。类型: {elementType.Name}, 对象: {behaviour.name}", behaviour);
            }
        }

        /// <summary>
        /// 注入单个组件
        /// </summary>
        private static void InjectSingleComponent(MonoBehaviour behaviour, FieldInfo field, AutoInjectAttribute searchComponent)
        {
            Component comp;

            // 根据 AutoInjectAttribute 配置查找组件
            if (string.IsNullOrEmpty(searchComponent.Label))
            {
                // 如果没有指定标签，使用默认的 GetComponent 查找
                comp = behaviour.GetComponent(field.FieldType);
            }
            else
            {
                // 如果指定了标签，使用 QueryComponent 按名称查找
                comp = behaviour.QueryComponent(field.FieldType, searchComponent.Label, searchComponent.IncludeInactive);
            }

            // 检查组件查找是否成功
            if (comp == null)
            {
                Debug.LogError($"[AutoInject] 未找到字段 '{field.Name}' 所需的组件。类型: {field.FieldType.Name}, 标签: {searchComponent.Label ?? "空"}, 对象: {behaviour.name}", behaviour);
                return;
            }

            // 将找到的组件赋值给字段
            field.SetValue(behaviour, comp);
        }

        /// <summary>
        /// 注入集合组件
        /// </summary>
        private static void InjectCollectionComponents(MonoBehaviour behaviour, FieldInfo field, AutoInjectAttribute searchComponent)
        {
            Type elementType = GetCollectionElementType(field.FieldType);
            if (elementType == null || !typeof(Component).IsAssignableFrom(elementType))
            {
                Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 的集合元素类型 '{elementType?.Name}' 不是 Component 类型，已跳过...", behaviour);
                return;
            }

            Component[] components;

            // 根据 AutoInjectAttribute 配置查找组件集合
            if (string.IsNullOrEmpty(searchComponent.Label))
            {
                // 如果没有指定标签，使用默认的 GetComponents 查找所有组件
                components = behaviour.GetComponentsInChildren(elementType, searchComponent.IncludeInactive);
            }
            else
            {
                // 如果指定了标签，使用 QueryComponents 按名称查找
                components = QueryComponents(behaviour, elementType, searchComponent.Label, searchComponent.IncludeInactive);
            }

            // 将找到的组件集合转换为目标集合类型并赋值给字段
            object collection = ConvertToCollectionType(components, field.FieldType, elementType);
            field.SetValue(behaviour, collection);

            // 输出查找结果信息
            if (components.Length == 0)
            {
                Debug.LogWarning($"[AutoInject] 字段 '{field.Name}' 未找到任何匹配的组件。类型: {elementType.Name}, 标签: {searchComponent.Label ?? "空"}, 对象: {behaviour.name}", behaviour);
            }
            else
            {
                Debug.Log($"[AutoInject] 字段 '{field.Name}' 找到 {components.Length} 个匹配的组件。类型: {elementType.Name}, 标签: {searchComponent.Label ?? "空"}, 对象: {behaviour.name}", behaviour);
            }
        }

        /// <summary>
        /// 检查类型是否为集合类型
        /// </summary>
        private static bool IsCollectionType(Type type)
        {
            return type.IsArray || (type.IsGenericType && typeof(IEnumerable<>).IsAssignableFrom(type.GetGenericTypeDefinition()));
        }

        /// <summary>
        /// 获取集合的元素类型
        /// </summary>
        private static Type GetCollectionElementType(Type collectionType)
        {
            if (collectionType.IsArray)
            {
                return collectionType.GetElementType();
            }
            else if (collectionType.IsGenericType)
            {
                return collectionType.GetGenericArguments()[0];
            }

            return null;
        }

        /// <summary>
        /// 按名称查询多个组件
        /// </summary>
        private static Component[] QueryComponents(Component original, Type type, string name, bool includeInactive = true)
        {
            if (original == null)
            {
                Debug.LogError("[AutoInject] QueryComponents 参数 original 不能为 null", original as MonoBehaviour);
                return Array.Empty<Component>();
            }

            if (type == null)
            {
                Debug.LogError("[AutoInject] QueryComponents 参数 type 不能为 null", original as MonoBehaviour);
                return Array.Empty<Component>();
            }

            if (!typeof(Component).IsAssignableFrom(type))
            {
                Debug.LogError($"[AutoInject] QueryComponents 类型 {type.Name} 必须继承自 Component", original as MonoBehaviour);
                return Array.Empty<Component>();
            }

            if (string.IsNullOrEmpty(name))
            {
                Debug.LogError("[AutoInject] QueryComponents 名字不能为空", original as MonoBehaviour);
                return Array.Empty<Component>();
            }

            Component[] components = original.GetComponentsInChildren(type, includeInactive);
            return components.Where(c => c.name.Trim().Equals(name)).ToArray();
        }

        /// <summary>
        /// 将组件数组转换为目标集合类型
        /// </summary>
        private static object ConvertToCollectionType(Component[] components, Type targetType, Type elementType)
        {
            if (targetType.IsArray)
            {
                Array array = Array.CreateInstance(elementType, components.Length);
                Array.Copy(components, array, components.Length);
                return array;
            }

            if (targetType.IsGenericType)
            {
                Type genericTypeDefinition = targetType.GetGenericTypeDefinition();

                if (genericTypeDefinition == typeof(List<>))
                {
                    Type listType = typeof(List<>).MakeGenericType(elementType);
                    object list = Activator.CreateInstance(listType);
                    MethodInfo addMethod = listType.GetMethod("Add");

                    foreach (Component component in components)
                    {
                        addMethod?.Invoke(list, new object[] { component });
                    }

                    return list;
                }

                if (genericTypeDefinition == typeof(IList<>) || genericTypeDefinition == typeof(ICollection<>))
                {
                    // 对于接口类型，创建 List<> 实例
                    Type listType = typeof(List<>).MakeGenericType(elementType);
                    object list = Activator.CreateInstance(listType);
                    MethodInfo addMethod = listType.GetMethod("Add");

                    foreach (Component component in components)
                    {
                        addMethod?.Invoke(list, new object[] { component });
                    }

                    return list;
                }
            }

            throw new NotSupportedException($"不支持的集合类型: {targetType.Name}");
        }
    }
}